//Michele Gregori 2009 miclegr@gmail.com

#ifndef DQDEFORMER_H
#define DQDEFORMER_H

#include<vector>
#include<cmath>
#include"MDualQuaternion.h"

#include<maya/MFnMatrixAttribute.h>
#include<maya/MFnNumericAttribute.h>
#include<maya/MFnTypedAttribute.h>
#include<maya/MDoubleArray.h>
#include<maya/MFnDoubleArrayData.h>
#include<maya/MFnMessageAttribute.h>
#include<maya/MFnMesh.h>
#include<maya/MFnMeshData.h>
#include<maya/MMatrix.h>
#include<maya/MTransformationMatrix.h>
#include<maya/MFnMatrixData.h>
#include<maya/MDataHandle.h>
#include<maya/MPoint.h>
#include<maya/MPointArray.h>
#include<maya/MDGModifier.h>
#include<maya/MPlugArray.h>
#include<maya/MPlug.h>
#include <maya/MPxDeformerNode.h>
#include <maya/MTypeId.h>

using namespace std;


class indexedWeight{
	public:
	double *weight;
	unsigned int *index;
	static bool comp(indexedWeight &first,indexedWeight &last){
		return first.weight<last.weight;
	}
};

typedef std::vector<MDualQuaternion*> AMDualQuaternion;
typedef std::vector<MMatrix*> AMMatrix;
typedef std::vector<indexedWeight> AIndexedWeight;
typedef std::vector<AIndexedWeight> AAIndexedWeight;
typedef std::vector<int> AInt;
typedef AAIndexedWeight::iterator iter;


class dqDeformer: public MPxDeformerNode{
	public:
	virtual void postConstructor();
	static void *creator();
	static MStatus initialize();
	virtual MStatus compute(const MPlug &plug,MDataBlock &block); 	
	virtual MStatus setDependentsDirty(const MPlug &plugBeingDirtied,MPlugArray &affectedPlugs);
	virtual MStatus connectionMade(const MPlug &plug, const MPlug &otherPlug,bool asSrc);
	virtual MStatus connectionBroken(const MPlug &plug, const MPlug &otherPlug,bool asSrc);
	virtual MStatus shouldSave(const MPlug& inPlug, bool& outResult);

	static MTypeId id;
	static MObject matrix;
	static MObject preBindMatrix;
	static MObject geomMatrix;
	static MObject lockWeights;
	static MObject paintWeight;
	static MObject paintTrans;
	static MObject paintArrDirty;
	static MObject bindPose;
	
	private:
	
	bool firstTime;
	int inCreation;
	
	MObject MThis;
	MObject geomData;
	MFnMesh *meshFn;
	
	AMDualQuaternion dqData;
	AMMatrix bindData;
	AMDualQuaternion dqMesh;
	AAIndexedWeight weightListData;
	MMatrix geomMatrixData;
	
	AInt dqDirty;
	AInt vtxDirty;
	std::vector<MPoint> initialMesh;
	
	std::vector<bool*> lockedJoint;
	int paintIndex;
	bool evalWeight;
};

#endif
